#include "online_table.h"
#include "utils.h"
#include "cstring"

using namespace std;

OnlineTable::~OnlineTable()
{
    OnlineItem *p = root_;
    while (p)
    {
        OnlineItem *temp = p;
        p = p->next;
        delete temp;
    }
}

int OnlineTable::Insert(std::string username, std::string alias, bool isOnline)
{
    OnlineItem *item = new OnlineItem;
    item->username = username;
    item->alias = alias;
    Utils utils;
    item->id = utils.StringHashCode(username.c_str());
    item->isOnline = false;
    item->pre = nullptr;
    item->next = nullptr;
    // 如果根节点为空，创建第一个节点
    if (!root_)
    {
        root_ = item;
        size_ = 1;
        return size_;
    }
    // 后续按照用户名散列后的值从大到小排列
    OnlineItem *p = root_;
    while (p)
    {
        if (p->id <= item->id)
        {
            break;
        }
        p = p->next;
    }
    item->next = p->next;
    p->next = item;
    size_++;
    return size_;
}

bool OnlineTable::Online(unsigned int id)
{
    OnlineItem *p = root_;
    while (p)
    {
        if (p->id == id)
        {
            if (!p->isOnline)
            {
                p->isOnline = true;
                return true;
            }
            return false;
        }
        p = p->next;
    }
    return false;
}

void OnlineTable::Offline(unsigned int id)
{
    OnlineItem *p = root_;
    while (p)
    {
        if (p->id == id)
        {
            p->isOnline = false;
            break;
        }
        p = p->next;
    }
}

int OnlineTable::size() const
{
    return size_;
}

OnlineItem *OnlineTable::FindByUsername(string username)
{
    OnlineItem *p = root_;
    while (p)
    {
        if (p->username == username)
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}

OnlineItem *OnlineTable::FindByAlias(string alias)
{
    OnlineItem *p = root_;
    while (p)
    {
        if (p->alias == alias)
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}

std::map<unsigned int, std::string> OnlineTable::GetOnlineTableRef()
{
    map<unsigned int, string> ref;
    OnlineItem *p = root_;
    while (p)
    {
        if (p->isOnline)
        {
            ref[p->id] = p->alias;
        }
        p = p->next;
    }
    return ref;
}